package vashion.azeroth.common.encrypt;


import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;



public class AesEncrypt {

    public static String Decrypt(String sSrc, String sKey) {   
            //判断Key是否正确
            if (sKey == null) {
            	throw new IllegalArgumentException("sKey is null");
            }
            //判断Key是否为16位
            if (sKey.length() != 16) {
            	throw new IllegalArgumentException("sKey's length must be 16");
            }
            AesCrypImpl aesCryp = new AesCrypImpl();
    		aesCryp.setAlgorithm("AES");
    		aesCryp.setTransformation("AES/ECB/PKCS5Padding");
    		aesCryp.setKey(sKey);  
            return aesCryp.dectypt(sSrc);    
    }
    
    public static String Encrypt(String sSrc, String sKey) throws Exception {
    	//判断Key是否正确
        if (sKey == null) {
        	throw new IllegalArgumentException("sKey is null");
        }
        //判断Key是否为16位
        if (sKey.length() != 16) {
        	throw new IllegalArgumentException("sKey's length must be 16");
        }
        AesCrypImpl aesCryp = new AesCrypImpl();
		aesCryp.setAlgorithm("AES");
		aesCryp.setTransformation("AES/ECB/PKCS5Padding");
		aesCryp.setKey(sKey);  
        return aesCryp.encrypt(sSrc); 
    }
    @SuppressWarnings("unused")
	private static byte[] hex2byte(String strhex) {
        if (strhex == null) {
            return null;
        }
        int l = strhex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
        }
        return b;
    }
    
    
    @SuppressWarnings("unused")
	private static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }
    
    
   private static class AesCrypImpl {

    	private String algorithm;

    	private String transformation;

    	private String key;

    	private String provider;

    	private ThreadLocal<JavaCrypto> local = new ThreadLocal<JavaCrypto>();

    	private JavaCrypto getLocalCrypto() {
    		JavaCrypto current = local.get();
    		if (current == null) {
    			current = new JavaCrypto(algorithm, transformation, key, provider);
    			local.set(current);
    		}
    		return current;
    	}

    	private static class JavaCrypto {
    		private Cipher enCipher;

    		private Cipher deCipher;

    		public JavaCrypto(String algorithm, String transformation, String key,
    				String provider) {
    			super();
    			try {
    				SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(),
    						algorithm);
    				if (provider == null) {
    					enCipher = Cipher.getInstance(transformation);
    					deCipher = Cipher.getInstance(transformation);
    				} else {
    					enCipher = Cipher.getInstance(transformation, provider);
    					deCipher = Cipher.getInstance(transformation, provider);
    				}
    				enCipher.init(Cipher.ENCRYPT_MODE, secretKey);
    				deCipher.init(Cipher.DECRYPT_MODE, secretKey);
    			} catch (NoSuchAlgorithmException e) {
    				throw new RuntimeException(e);
    			} catch (NoSuchPaddingException e) {
    				throw new RuntimeException(e);
    			} catch (InvalidKeyException e) {
    				throw new RuntimeException(e);
    			} catch (NoSuchProviderException e) {
    				throw new RuntimeException(e);
    			}
    		}

    		public byte[] encrypt(byte[] bs) {
    			try {
    				return enCipher.doFinal(bs);
    			} catch (IllegalBlockSizeException e) {
    				throw new RuntimeException(e);
    			} catch (BadPaddingException e) {
    				throw new RuntimeException(e);
    			}
    		}

    		public byte[] dectypt(byte[] bs) {
    			try {
    				return deCipher.doFinal(bs);
    			} catch (IllegalBlockSizeException e) {
    				throw new RuntimeException(e);
    			} catch (BadPaddingException e) {
    				throw new RuntimeException(e);
    			}
    		}
    	}

    	public  String dectypt(String s) {
    		return dectypt(s, null);
    	}

    	public String dectypt(String s, String charset) {
    		if (s == null) {
    			throw new NullPointerException("dectypt string can't be null");
    		}
    		try {
    			byte[] bs = (charset != null) ? Base64.decodeBase64(s
    					.getBytes(charset)) : Base64.decodeBase64(s.getBytes());
    			bs = dectypt(bs);
    			String back = (charset != null) ? new String(bs, charset)
    					: new String(bs);
    			back = back.trim();
    			return back;
    		} catch (UnsupportedEncodingException e) {
    			throw new RuntimeException(e);
    		}
    	}

    	public byte[] dectypt(byte[] bytes) {
    		if (bytes == null) {
    			throw new NullPointerException("dectypt bytes can't be null");
    		}
    		return this.getLocalCrypto().dectypt(bytes);
    	}

    	public String encrypt(String s) {
    		return encrypt(s, null);
    	}

    	public String encrypt(String s, String charset) {
    		if (s == null) {
    			throw new NullPointerException("encrypt string can't be null");
    		}
    		try {
    			byte[] bs = (charset != null) ? this.encrypt(s.getBytes(charset))
    					: this.encrypt(s.getBytes());
    			bs = Base64.encodeBase64(bs);
    			return (charset != null) ? new String(bs, charset) : new String(bs);
    		} catch (UnsupportedEncodingException e) {
    			throw new RuntimeException(e);
    		}
    	}

    	public byte[] encrypt(byte[] bytes) {
    		if (bytes == null) {
    			throw new NullPointerException("encrypt bytes can't be null");
    		}
    		return this.getLocalCrypto().encrypt(bytes);
    	}

    	@SuppressWarnings("unused")
		public String getAlgorithm() {
    		return algorithm;
    	}

    	public void setAlgorithm(String algorithm) {
    		this.algorithm = algorithm;
    	}

    	@SuppressWarnings("unused")
		public String getKey() {
    		return key;
    	}

    	public void setKey(String key) {
    		this.key = key;
    	}

    	@SuppressWarnings("unused")
		public String getTransformation() {
    		return transformation;
    	}

    	public void setTransformation(String transformation) {
    		this.transformation = transformation;
    	}

    	@SuppressWarnings("unused")
		public String getProvider() {
    		return provider;
    	}

    	@SuppressWarnings("unused")
		public void setProvider(String provider) {
    		this.provider = provider;
    	}

    }
  
    
}